//////////////////////////////////////////////////////////////////////////

#include "network_packets.h"
#include <iostream>

//////////////////////////////////////////////////////////////////////////


bool ClientPacket::operator==( const ClientPacket& _rhs )
{
    return m_KeyFlags == _rhs.m_KeyFlags &&
           m_MousePosition == _rhs.m_MousePosition;
}


//////////////////////////////////////////////////////////////////////////


bool ClientPacket::operator!=( const ClientPacket& _rhs )
{
    return !operator==(_rhs);
}


//////////////////////////////////////////////////////////////////////////


bool ServerPacket::operator==( const ServerPacket& _rhs )
{
    return m_Players == _rhs.m_Players   &&
           m_Bullets == _rhs.m_Bullets;
}


//////////////////////////////////////////////////////////////////////////


bool ServerPacket::operator!=( const ServerPacket& _rhs )
{
    return !operator==(_rhs);
}


//////////////////////////////////////////////////////////////////////////


int ClientPacket::Size() const
{
    return sizeof(unsigned int) + sizeof(short) * 2;
}

//////////////////////////////////////////////////////////////////////////


void ClientPacket::FromStr( const char* _str )
{
    // Remove const
    char* str = const_cast<char*>(_str);
    int bytePosition = 0;

    // First 4 bytes are key flags
    unsigned int* keyFlagsPtr = reinterpret_cast<unsigned int*>(&str[bytePosition]);
    m_KeyFlags = *keyFlagsPtr;
    bytePosition += sizeof(unsigned int);

    // Next 2 bytes are X mouse position
    short* mouseXPtr = reinterpret_cast<short*>(&str[bytePosition]);
    m_MousePosition.first = *mouseXPtr;
    bytePosition += sizeof(short);

    // Next 2 bytes are Y mouse position
    short* mouseYPtr = reinterpret_cast<short*>(&str[bytePosition]);
    m_MousePosition.second = *mouseYPtr;
    bytePosition += sizeof(short);

    /*std::cout << "Packet received!"
        << "\nClient ID: " << m_ClientID
        << "\nKeyFlags: " << m_KeyFlags
        << "\nMouse: " << m_MousePosition.first << " " << m_MousePosition.second << std::endl;*/
}


//////////////////////////////////////////////////////////////////////////


std::vector<char> ClientPacket::ToStr() const
{
    std::vector<char> str( Size() );
    int bytePosition = 0;

    // First 4 bytes are key flags
    unsigned int* keyFlagsPtr = reinterpret_cast<unsigned int*>(&str[bytePosition]);
    *keyFlagsPtr = m_KeyFlags;
    bytePosition += sizeof(unsigned int);

    // Next 2 bytes are X mouse position
    short* mouseXPtr = reinterpret_cast<short*>(&str[bytePosition]);
    *mouseXPtr = m_MousePosition.first;
    bytePosition += sizeof(short);

    // Next 2 bytes are Y mouse position
    short* mouseYPtr = reinterpret_cast<short*>(&str[bytePosition]);
    *mouseYPtr = m_MousePosition.second;
    bytePosition += sizeof(short);

    /*std::cout << "Packet sent!"
        << "\nClient ID: " << m_ClientID
        << "\nKeyFlags: " << m_KeyFlags
        << "\nMouse: " << m_MousePosition.first << " " << m_MousePosition.second << std::endl;*/

    // Return resulting string
    return str;
}


//////////////////////////////////////////////////////////////////////////


int ServerPacket::Size() const
{
    return
        m_Players.size() * sizeof(short) * 2 + sizeof(short) +
        m_Bullets.size() * sizeof(short) * 2 + sizeof(short);
}


//////////////////////////////////////////////////////////////////////////


std::vector<char> ServerPacket::ToStr() const
{
    std::vector<char> str( Size() + sizeof(short) );
    int bytePosition = 0;

    // First 2 bytes are packet size
    short* packetSize = reinterpret_cast<short*>(&str[bytePosition]);
    *packetSize = Size();
    bytePosition += sizeof(short);

    // First 2 bytes are players count
    short* playersCount = reinterpret_cast<short*>(&str[bytePosition]);
    *playersCount = static_cast<short>( m_Players.size() );
    bytePosition += sizeof(short);

    // Next playersCount*2*2 bytes are players coordinates
    for (size_t i = 0; i < m_Players.size(); ++i)
    {
        short* playerXPos = reinterpret_cast<short*>(&str[bytePosition]);
        *playerXPos = static_cast<short>( m_Players[i].first );
        bytePosition += sizeof(short);

        short* playerYPos = reinterpret_cast<short*>(&str[bytePosition]);
        *playerYPos = static_cast<short>( m_Players[i].second );
        bytePosition += sizeof(short);
    }

    // Next 2 bytes are bullets count
    short* bulletsCount = reinterpret_cast<short*>(&str[bytePosition]);
    *bulletsCount = static_cast<short>( m_Bullets.size() );
    bytePosition += sizeof(short);

    // Next bulletsCount*2*2 bytes are bullets coordinates
    for (size_t i = 0; i < m_Bullets.size(); ++i)
    {
        short* bulletXPos = reinterpret_cast<short*>(&str[bytePosition]);
        *bulletXPos = static_cast<short>( m_Bullets[i].first );
        bytePosition += sizeof(short);

        short* bulletYPos = reinterpret_cast<short*>(&str[bytePosition]);
        *bulletYPos = static_cast<short>( m_Bullets[i].second );
        bytePosition += sizeof(short);
    }

    return str;
}


//////////////////////////////////////////////////////////////////////////


void ServerPacket::FromStr( const char* _str )
{
    // Remove const
    char* str = const_cast<char*>(_str);
    int bytePosition = 0;

    // First 2 bytes are players count
    short* playersCountPtr = reinterpret_cast<short*>(&str[bytePosition]);
    bytePosition += sizeof(short);

    short playersCount = *playersCountPtr;
    m_Players.resize(playersCount);

    // Next playersCount*2*2 bytes are players coordinates
    for (short i = 0; i < playersCount; ++i)
    {
        short* playerXPos = reinterpret_cast<short*>(&str[bytePosition]);
        bytePosition += sizeof(short);
        m_Players[i].first = *playerXPos;

        short* playerYPos = reinterpret_cast<short*>(&str[bytePosition]);
        bytePosition += sizeof(short);
        m_Players[i].second = *playerYPos;
    }

    // Next 2 bytes are bullets count
    short* bulletsCountPtr = reinterpret_cast<short*>(&str[bytePosition]);
    bytePosition += sizeof(short);

    short bulletsCount = *bulletsCountPtr;
    m_Bullets.resize(bulletsCount);

    // Next bulletsCount*2*2 bytes are bullets coordinates
    for (short i = 0; i < bulletsCount; ++i)
    {
        short* bulletXPos = reinterpret_cast<short*>(&str[bytePosition]);
        bytePosition += sizeof(short);
        m_Bullets[i].first = *bulletXPos;

        short* bulletYPos = reinterpret_cast<short*>(&str[bytePosition]);
        bytePosition += sizeof(short);
        m_Bullets[i].second = *bulletYPos;
    }
}


//////////////////////////////////////////////////////////////////////////
